using System;
using System.Collections.Generic;

//
// * Copyright (c) 2002-2009 "Neo Technology,"
// *     Network Engine for Objects in Lund AB [http://neotechnology.com]
// *
// * This file is part of Neo4j.
// * 
// * Neo4j is free software: you can redistribute it and/or modify
// * it under the terms of the GNU Affero General Public License as
// * published by the Free Software Foundation, either version 3 of the
// * License, or (at your option) any later version.
// * 
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// * GNU Affero General Public License for more details.
// * 
// * You should have received a copy of the GNU Affero General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// 
namespace org.neo4j.kernel.impl.nioneo.store
{


	using XAException = javax.transaction.xa.XAException;
	using XAResource = javax.transaction.xa.XAResource;
	using Xid = javax.transaction.xa.Xid;

	using Node = org.neo4j.graphdb.Node;
	using Relationship = org.neo4j.graphdb.Relationship;
	using RelationshipType = org.neo4j.graphdb.RelationshipType;
	using AbstractNeo4jTestCase = org.neo4j.kernel.impl.AbstractNeo4jTestCase;
	using LockReleaser = org.neo4j.kernel.impl.core.LockReleaser;
	using PropertyIndex = org.neo4j.kernel.impl.core.PropertyIndex;
	using NeoStore = org.neo4j.kernel.impl.nioneo.store.NeoStore;
	using PropertyData = org.neo4j.kernel.impl.nioneo.store.PropertyData;
	using PropertyRecord = org.neo4j.kernel.impl.nioneo.store.PropertyRecord;
	using PropertyStore = org.neo4j.kernel.impl.nioneo.store.PropertyStore;
	using PropertyType = org.neo4j.kernel.impl.nioneo.store.PropertyType;
	using RelationshipChainPosition = org.neo4j.kernel.impl.nioneo.store.RelationshipChainPosition;
	using RelationshipData = org.neo4j.kernel.impl.nioneo.store.RelationshipData;
	using RelationshipTypeData = org.neo4j.kernel.impl.nioneo.store.RelationshipTypeData;
	using NeoStoreXaConnection = org.neo4j.kernel.impl.nioneo.xa.NeoStoreXaConnection;
	using NeoStoreXaDataSource = org.neo4j.kernel.impl.nioneo.xa.NeoStoreXaDataSource;
	using NodeEventConsumer = org.neo4j.kernel.impl.nioneo.xa.NodeEventConsumer;
	using RelationshipEventConsumer = org.neo4j.kernel.impl.nioneo.xa.RelationshipEventConsumer;
	using RelationshipTypeEventConsumer = org.neo4j.kernel.impl.nioneo.xa.RelationshipTypeEventConsumer;
	using LockManager = org.neo4j.kernel.impl.transaction.LockManager;
	using XidImpl = org.neo4j.kernel.impl.transaction.XidImpl;
	using ArrayMap = org.neo4j.kernel.impl.util.ArrayMap;

	public class TestNeoStore : AbstractNeo4jTestCase
	{
		public TestNeoStore(string testName) : base(testName)
		{
		}

		private NodeEventConsumer nStore;
		private PropertyStore pStore;
		private RelationshipTypeEventConsumer relTypeStore;
		private RelationshipEventConsumer rStore;

		private NeoStoreXaDataSource ds;
		private NeoStoreXaConnection xaCon;

		public override void setUp()
		{
			base.setUp();
			try
			{
				NeoStore.createStore("neo");
			}
			catch (Exception e)
			{
				fail("" + e);
			}
		}

		private class MyPropertyIndex : org.neo4j.kernel.impl.core.PropertyIndex
		{
			private static Map<string, PropertyIndex> stringToIndex = new Dictionary<string, PropertyIndex>();
			private static Map<int, PropertyIndex> intToIndex = new Dictionary<int, PropertyIndex>();

			protected internal MyPropertyIndex(string key, int keyId) : base(key, keyId)
			{
			}

			public static Iterable<PropertyIndex> index(string key)
			{
				if (stringToIndex.containsKey(key))
				{
					return Arrays.asList(new PropertyIndex[] { stringToIndex.get(key) });
				}
				return Collections.EMPTY_LIST;
			}

			public static PropertyIndex getIndexFor(int index)
			{
				return intToIndex.get(index);
			}

			public static void add(MyPropertyIndex index)
			{
			// TODO Auto-generated method stub
				stringToIndex.put(index.Key, index);
				intToIndex.put(index.getKeyId(), index);
			}
		}

		private PropertyIndex createDummyIndex(int id, string key)
		{
			MyPropertyIndex index = new MyPropertyIndex(key, id);
			MyPropertyIndex.Add(index);
			return index;
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void initializeStores() throws IOException
		private void initializeStores()
		{
			try
			{
				LockManager lockManager = getEmbeddedGraphDb().getConfig().getLockManager();
				LockReleaser lockReleaser = getEmbeddedGraphDb().getConfig().getLockReleaser();
				ds = new NeoStoreXaDataSource("neo", "nioneo_logical.log", lockManager, lockReleaser);
			}
			catch (InstantiationException e)
			{
				throw new IOException("" + e);
			}
			xaCon = (NeoStoreXaConnection) ds.getXaConnection();
			nStore = xaCon.getNodeConsumer();
			pStore = xaCon.getPropertyStore();
			relTypeStore = xaCon.getRelationshipTypeConsumer();
			rStore = xaCon.getRelationshipConsumer();
		}

		private Xid dummyXid;
		private sbyte txCount = (sbyte) 0;
		internal XAResource xaResource;

		private void startTx()
		{
			dummyXid = new XidImpl(new sbyte[txCount], new sbyte[txCount]);
			txCount++;
			xaResource = xaCon.getXaResource();
			try
			{
				xaResource.Start(dummyXid, XAResource.TMNOFLAGS);
			}
			catch (XAException e)
			{
				throw new RuntimeException(e);
			}
		}

		private void commitTx()
		{
			try
			{
				xaResource.end(dummyXid, XAResource.TMSUCCESS);
				xaResource.commit(dummyXid, true);
			}
			catch (XAException e)
			{
				throw new RuntimeException(e);
			}
		// xaCon.clearAllTransactions();
		}

		public virtual void tearDown()
		{
			base.tearDown();
			File file = new File("neo");
			file.delete();
			file = new File("neo.id");
			file.delete();
			file = new File("neo.nodestore.db");
			file.delete();
			file = new File("neo.nodestore.db.id");
			file.delete();
			file = new File("neo.propertystore.db");
			file.delete();
			file = new File("neo.propertystore.db.id");
			file.delete();
			file = new File("neo.propertystore.db.index");
			file.delete();
			file = new File("neo.propertystore.db.index.id");
			file.delete();
			file = new File("neo.propertystore.db.index.keys");
			file.delete();
			file = new File("neo.propertystore.db.index.keys.id");
			file.delete();
			file = new File("neo.propertystore.db.strings");
			file.delete();
			file = new File("neo.propertystore.db.strings.id");
			file.delete();
			file = new File("neo.propertystore.db.arrays");
			file.delete();
			file = new File("neo.propertystore.db.arrays.id");
			file.delete();
			file = new File("neo.relationshipstore.db");
			file.delete();
			file = new File("neo.relationshipstore.db.id");
			file.delete();
			file = new File("neo.relationshiptypestore.db");
			file.delete();
			file = new File("neo.relationshiptypestore.db.id");
			file.delete();
			file = new File("neo.relationshiptypestore.db.names");
			file.delete();
			file = new File("neo.relationshiptypestore.db.names.id");
			file.delete();
			file = new File(".");
			foreach (File nioFile in file.listFiles())
			{
				if (nioFile.Name.StartsWith("nioneo_logical.log"))
				{
					nioFile.delete();
				}
			}
		}

		private PropertyIndex index(string key)
		{
			Iterator<PropertyIndex> itr = MyPropertyIndex.index(key).GetEnumerator();
			if (!itr.MoveNext())
			{
				int id = ds.nextId(typeof(PropertyIndex));
				PropertyIndex index = createDummyIndex(id, key);
				xaCon.getPropertyIndexConsumer().createPropertyIndex(id, key);
				return index;
			}
			return itr.Current;
		}

		public virtual void testCreateNeoStore()
		{
			try
			{
				initializeStores();
				startTx();
			// setup test population
				int node1 = ds.nextId(typeof(Node));
				nStore.createNode(node1);
				int node2 = ds.nextId(typeof(Node));
				nStore.createNode(node2);
				int n1prop1 = pStore.nextId();
				int n1prop2 = pStore.nextId();
				int n1prop3 = pStore.nextId();
				nStore.addProperty(node1, n1prop1, index("prop1"), "string1");
				nStore.addProperty(node1, n1prop2, index("prop2"), new int(1));
				nStore.addProperty(node1, n1prop3, index("prop3"), new bool(true));

				int n2prop1 = pStore.nextId();
				int n2prop2 = pStore.nextId();
				int n2prop3 = pStore.nextId();
				nStore.addProperty(node2, n2prop1, index("prop1"), "string2");
				nStore.addProperty(node2, n2prop2, index("prop2"), new int(2));
				nStore.addProperty(node2, n2prop3, index("prop3"), new bool(false));

				int relType1 = ds.nextId(typeof(RelationshipType));
				relTypeStore.addRelationshipType(relType1, "relationshiptype1");
				int relType2 = ds.nextId(typeof(RelationshipType));
				relTypeStore.addRelationshipType(relType2, "relationshiptype2");
				int rel1 = ds.nextId(typeof(Relationship));
				rStore.createRelationship(rel1, node1, node2, relType1);
				int rel2 = ds.nextId(typeof(Relationship));
				rStore.createRelationship(rel2, node2, node1, relType2);
				int r1prop1 = pStore.nextId();
				int r1prop2 = pStore.nextId();
				int r1prop3 = pStore.nextId();
				rStore.addProperty(rel1, r1prop1, index("prop1"), "string1");
				rStore.addProperty(rel1, r1prop2, index("prop2"), new int(1));
				rStore.addProperty(rel1, r1prop3, index("prop3"), new bool(true));
				int r2prop1 = pStore.nextId();
				int r2prop2 = pStore.nextId();
				int r2prop3 = pStore.nextId();
				rStore.addProperty(rel2, r2prop1, index("prop1"), "string2");
				rStore.addProperty(rel2, r2prop2, index("prop2"), new int(2));
				rStore.addProperty(rel2, r2prop3, index("prop3"), new bool(false));
				commitTx();
				ds.Close();

				initializeStores();
				startTx();
			// validate node
				validateNodeRel1(node1, n1prop1, n1prop2, n1prop3, rel1, rel2, relType1, relType2);
				validateNodeRel2(node2, n2prop1, n2prop2, n2prop3, rel1, rel2, relType1, relType2);
			// validate rels
				validateRel1(rel1, r1prop1, r1prop2, r1prop3, node1, node2, relType1);
				validateRel2(rel2, r2prop1, r2prop2, r2prop3, node2, node1, relType2);
				validateRelTypes(relType1, relType2);
			// validate reltypes
				validateRelTypes(relType1, relType2);
				commitTx();
				ds.Close();

				initializeStores();
				startTx();
			// validate and delete rels
				deleteRel1(rel1, r1prop1, r1prop2, r1prop3, node1, node2, relType1);
				deleteRel2(rel2, r2prop1, r2prop2, r2prop3, node2, node1, relType2);
			// validate and delete nodes
				deleteNode1(node1, n1prop1, n1prop2, n1prop3);
				deleteNode2(node2, n2prop1, n2prop2, n2prop3);
				commitTx();
				ds.Close();

				initializeStores();
				startTx();
				assertEquals(false, nStore.loadLightNode(node1));
				assertEquals(false, nStore.loadLightNode(node2));
				testGetRels(new int[] { rel1, rel2 });
			// testGetProps( neoStore, new int[] {
			// n1prop1, n1prop2, n1prop3, n2prop1, n2prop2, n2prop3,
			// r1prop1, r1prop2, r1prop3, r2prop1, r2prop2, r2prop3
			// } );
				int[] nodeIds = new int[10];
				for (int i = 0; i < 3; i++)
				{
					nodeIds[i] = ds.nextId(typeof(Node));
					nStore.createNode(nodeIds[i]);
					nStore.addProperty(nodeIds[i], pStore.nextId(), index("nisse"), new int(10 - i));
				}
				for (int i = 0; i < 2; i++)
				{
					int id = ds.nextId(typeof(Relationship));
					rStore.createRelationship(id, nodeIds[i], nodeIds[i + 1], relType1);
					rStore.deleteRelationship(id);
				}
				for (int i = 0; i < 3; i++)
				{
					RelationshipChainPosition pos = rStore.getRelationshipChainPosition(nodeIds[i]);
					foreach (RelationshipData rel in rStore.getMoreRelationships(nodeIds[i], pos))
					{
						rStore.deleteRelationship(rel.getId());
					}
					nStore.deleteNode(nodeIds[i]);
				}
				commitTx();
				ds.Close();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				fail("" + e);
			}
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private Object getValue(PropertyRecord propertyRecord) throws IOException
		private object getValue(PropertyRecord propertyRecord)
		{
			PropertyType type = propertyRecord.getType();
			if (type == PropertyType.INT)
			{
				return (int) propertyRecord.getPropBlock();
			}
			if (type == PropertyType.STRING)
			{
				return pStore.getStringFor(propertyRecord);
			}
			if (type == PropertyType.BOOL)
			{
				if (propertyRecord.getPropBlock() == 1)
				{
					return Convert.ToBoolean(true);
				}
				return Convert.ToBoolean(false);
			}
			if (type == PropertyType.DOUBLE)
			{
				return new double(double.longBitsToDouble(propertyRecord.getPropBlock()));
			}
			if (type == PropertyType.FLOAT)
			{
				return new float(float.intBitsToFloat((int) propertyRecord.getPropBlock()));
			}
			if (type == PropertyType.LONG)
			{
				return propertyRecord.getPropBlock();
			}
			if (type == PropertyType.BYTE)
			{
				return (sbyte) propertyRecord.getPropBlock();
			}
			if (type == PropertyType.CHAR)
			{
				return (char) propertyRecord.getPropBlock();
			}
			if (type == PropertyType.ARRAY)
			{
				return pStore.getArrayFor(propertyRecord);
			}
			if (type == PropertyType.SHORT)
			{
				return (short) propertyRecord.getPropBlock();
			}
			throw new IOException("Unknown type");
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void validateNodeRel1(int node, int prop1, int prop2, int prop3, int rel1, int rel2, int relType1, int relType2) throws IOException
		private void validateNodeRel1(int node, int prop1, int prop2, int prop3, int rel1, int rel2, int relType1, int relType2)
		{
			assertTrue(nStore.loadLightNode(node));
			ArrayMap<int, PropertyData> props = nStore.getProperties(node);
			int count = 0;
			foreach (int keyId in props.Keys)
			{
				int id = props.get(keyId).getId();
				PropertyRecord record = pStore.getRecord(id);
				PropertyData data = new PropertyData(id, getValue(record));
				if (data.getId() == prop1)
				{
					assertEquals("prop1", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals("string1", data.Value);
					nStore.changeProperty(node, prop1, "-string1");
				}
				else if (data.getId() == prop2)
				{
					assertEquals("prop2", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new int(1), data.Value);
					nStore.changeProperty(node, prop2, new int(-1));
				}
				else if (data.getId() == prop3)
				{
					assertEquals("prop3", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new bool(true), data.Value);
					nStore.changeProperty(node, prop3, new bool(false));
				}
				else
				{
					throw new IOException();
				}
				count++;
			}
			assertEquals(3, count);
			count = 0;
			RelationshipChainPosition pos = rStore.getRelationshipChainPosition(node);
			foreach (RelationshipData rel in rStore.getMoreRelationships(node, pos))
			{
				if (rel.getId() == rel1)
				{
					assertEquals(node, rel.firstNode());
					assertEquals(relType1, rel.relationshipType());
				}
				else if (rel.getId() == rel2)
				{
					assertEquals(node, rel.secondNode());
					assertEquals(relType2, rel.relationshipType());
				}
				else
				{
					throw new IOException();
				}
				count++;
			}
			assertEquals(2, count);
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void validateNodeRel2(int node, int prop1, int prop2, int prop3, int rel1, int rel2, int relType1, int relType2) throws IOException
		private void validateNodeRel2(int node, int prop1, int prop2, int prop3, int rel1, int rel2, int relType1, int relType2)
		{
			assertTrue(nStore.loadLightNode(node));
			ArrayMap<int, PropertyData> props = nStore.getProperties(node);
			int count = 0;
			foreach (int keyId in props.Keys)
			{
				int id = props.get(keyId).getId();
				PropertyRecord record = pStore.getRecord(id);
				PropertyData data = new PropertyData(id, getValue(record));
				if (data.getId() == prop1)
				{
					assertEquals("prop1", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals("string2", data.Value);
					nStore.changeProperty(node, prop1, "-string2");
				}
				else if (data.getId() == prop2)
				{
					assertEquals("prop2", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new int(2), data.Value);
					nStore.changeProperty(node, prop2, new int(-2));
				}
				else if (data.getId() == prop3)
				{
					assertEquals("prop3", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new bool(false), data.Value);
					nStore.changeProperty(node, prop3, new bool(true));
				}
				else
				{
					throw new IOException();
				}
				count++;
			}
			assertEquals(3, count);
			count = 0;
			RelationshipChainPosition pos = rStore.getRelationshipChainPosition(node);
			foreach (RelationshipData rel in rStore.getMoreRelationships(node, pos))
			{
				if (rel.getId() == rel1)
				{
					assertEquals(node, rel.secondNode());
					assertEquals(relType1, rel.relationshipType());
				}
				else if (rel.getId() == rel2)
				{
					assertEquals(node, rel.firstNode());
					assertEquals(relType2, rel.relationshipType());
				}
				else
				{
					throw new IOException();
				}
				count++;
			}
			assertEquals(2, count);
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void validateRel1(int rel, int prop1, int prop2, int prop3, int firstNode, int secondNode, int relType) throws IOException
		private void validateRel1(int rel, int prop1, int prop2, int prop3, int firstNode, int secondNode, int relType)
		{
			ArrayMap<int, PropertyData> props = rStore.getProperties(rel);
			int count = 0;
			foreach (int keyId in props.Keys)
			{
				int id = props.get(keyId).getId();
				PropertyRecord record = pStore.getRecord(id);
				PropertyData data = new PropertyData(id, getValue(record));
				if (data.getId() == prop1)
				{
					assertEquals("prop1", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals("string1", data.Value);
					rStore.changeProperty(rel, prop1, "-string1");
				}
				else if (data.getId() == prop2)
				{
					assertEquals("prop2", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new int(1), data.Value);
					rStore.changeProperty(rel, prop2, new int(-1));
				}
				else if (data.getId() == prop3)
				{
					assertEquals("prop3", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new bool(true), data.Value);
					rStore.changeProperty(rel, prop3, new bool(false));
				}
				else
				{
					throw new IOException();
				}
				count++;
			}
			assertEquals(3, count);
			RelationshipData relData = rStore.getRelationship(rel);
			assertEquals(firstNode, relData.firstNode());
			assertEquals(secondNode, relData.secondNode());
			assertEquals(relType, relData.relationshipType());
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void validateRel2(int rel, int prop1, int prop2, int prop3, int firstNode, int secondNode, int relType) throws IOException
		private void validateRel2(int rel, int prop1, int prop2, int prop3, int firstNode, int secondNode, int relType)
		{
			ArrayMap<int, PropertyData> props = rStore.getProperties(rel);
			int count = 0;
			foreach (int keyId in props.Keys)
			{
				int id = props.get(keyId).getId();
				PropertyRecord record = pStore.getRecord(id);
				PropertyData data = new PropertyData(id, getValue(record));
				if (data.getId() == prop1)
				{
					assertEquals("prop1", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals("string2", data.Value);
					rStore.changeProperty(rel, prop1, "-string2");
				}
				else if (data.getId() == prop2)
				{
					assertEquals("prop2", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new int(2), data.Value);
					rStore.changeProperty(rel, prop2, new int(-2));
				}
				else if (data.getId() == prop3)
				{
					assertEquals("prop3", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new bool(false), data.Value);
					rStore.changeProperty(rel, prop3, new bool(true));
				}
				else
				{
					throw new IOException();
				}
				count++;
			}
			assertEquals(3, count);
			RelationshipData relData = rStore.getRelationship(rel);
			assertEquals(firstNode, relData.firstNode());
			assertEquals(secondNode, relData.secondNode());
			assertEquals(relType, relData.relationshipType());
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void validateRelTypes(int relType1, int relType2) throws IOException
		private void validateRelTypes(int relType1, int relType2)
		{
			RelationshipTypeData data = relTypeStore.getRelationshipType(relType1);
			assertEquals(relType1, data.getId());
			assertEquals("relationshiptype1", data.Name);
			data = relTypeStore.getRelationshipType(relType2);
			assertEquals(relType2, data.getId());
			assertEquals("relationshiptype2", data.Name);
			RelationshipTypeData[] allData = relTypeStore.getRelationshipTypes();
			assertEquals(2, allData.Length);
			for (int i = 0; i < 2; i++)
			{
				if (allData[i].getId() == relType1)
				{
					assertEquals(relType1, allData[i].getId());
					assertEquals("relationshiptype1", allData[i].Name);
				}
				else if (allData[i].getId() == relType2)
				{
					assertEquals(relType2, allData[i].getId());
					assertEquals("relationshiptype2", allData[i].Name);
				}
				else
				{
					throw new IOException();
				}
			}
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void deleteRel1(int rel, int prop1, int prop2, int prop3, int firstNode, int secondNode, int relType) throws IOException
		private void deleteRel1(int rel, int prop1, int prop2, int prop3, int firstNode, int secondNode, int relType)
		{
			ArrayMap<int, PropertyData> props = rStore.getProperties(rel);
			int count = 0;
			foreach (int keyId in props.Keys)
			{
				int id = props.get(keyId).getId();
				PropertyRecord record = pStore.getRecord(id);
				PropertyData data = new PropertyData(id, getValue(record));
				if (data.getId() == prop1)
				{
					assertEquals("prop1", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals("-string1", data.Value);
				}
				else if (data.getId() == prop2)
				{
					assertEquals("prop2", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new int(-1), data.Value);
				}
				else if (data.getId() == prop3)
				{
					assertEquals("prop3", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new bool(false), data.Value);
					rStore.removeProperty(rel, prop3);
				}
				else
				{
					throw new IOException();
				}
				count++;
			}
			assertEquals(3, count);
			assertEquals(2, rStore.getProperties(rel).size());
			RelationshipData relData = rStore.getRelationship(rel);
			assertEquals(firstNode, relData.firstNode());
			assertEquals(secondNode, relData.secondNode());
			assertEquals(relType, relData.relationshipType());
			rStore.deleteRelationship(rel);
			RelationshipChainPosition firstPos = rStore.getRelationshipChainPosition(firstNode);
			Iterator<RelationshipData> first = rStore.getMoreRelationships(firstNode, firstPos).GetEnumerator();
			first.Current;
			RelationshipChainPosition secondPos = rStore.getRelationshipChainPosition(secondNode);
			Iterator<RelationshipData> second = rStore.getMoreRelationships(secondNode, secondPos).GetEnumerator();
			second.Current;
			assertTrue(!first.MoveNext());
			assertTrue(!second.MoveNext());
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void deleteRel2(int rel, int prop1, int prop2, int prop3, int firstNode, int secondNode, int relType) throws IOException
		private void deleteRel2(int rel, int prop1, int prop2, int prop3, int firstNode, int secondNode, int relType)
		{
			ArrayMap<int, PropertyData> props = rStore.getProperties(rel);
			int count = 0;
			foreach (int keyId in props.Keys)
			{
				int id = props.get(keyId).getId();
				PropertyRecord record = pStore.getRecord(id);
				PropertyData data = new PropertyData(id, getValue(record));
				if (data.getId() == prop1)
				{
					assertEquals("prop1", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals("-string2", data.Value);
				}
				else if (data.getId() == prop2)
				{
					assertEquals("prop2", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new int(-2), data.Value);
				}
				else if (data.getId() == prop3)
				{
					assertEquals("prop3", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new bool(true), data.Value);
					rStore.removeProperty(rel, prop3);
				}
				else
				{
					throw new IOException();
				}
				count++;
			}
			assertEquals(3, count);
			assertEquals(2, rStore.getProperties(rel).size());
			RelationshipData relData = rStore.getRelationship(rel);
			assertEquals(firstNode, relData.firstNode());
			assertEquals(secondNode, relData.secondNode());
			assertEquals(relType, relData.relationshipType());
			rStore.deleteRelationship(rel);
			RelationshipChainPosition firstPos = rStore.getRelationshipChainPosition(firstNode);
			Iterator<RelationshipData> first = rStore.getMoreRelationships(firstNode, firstPos).GetEnumerator();
			RelationshipChainPosition secondPos = rStore.getRelationshipChainPosition(secondNode);
			Iterator<RelationshipData> second = rStore.getMoreRelationships(secondNode, secondPos).GetEnumerator();
			assertTrue(!first.MoveNext());
			assertTrue(!second.MoveNext());
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void deleteNode1(int node, int prop1, int prop2, int prop3) throws IOException
		private void deleteNode1(int node, int prop1, int prop2, int prop3)
		{
			ArrayMap<int, PropertyData> props = nStore.getProperties(node);
			int count = 0;
			foreach (int keyId in props.Keys)
			{
				int id = props.get(keyId).getId();
				PropertyRecord record = pStore.getRecord(id);
				PropertyData data = new PropertyData(id, getValue(record));
				if (data.getId() == prop1)
				{
					assertEquals("prop1", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals("-string1", data.Value);
				}
				else if (data.getId() == prop2)
				{
					assertEquals("prop2", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new int(-1), data.Value);
				}
				else if (data.getId() == prop3)
				{
					assertEquals("prop3", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new bool(false), data.Value);
					nStore.removeProperty(node, prop3);
				}
				else
				{
					throw new IOException();
				}
				count++;
			}
			assertEquals(3, count);
			assertEquals(2, nStore.getProperties(node).size());

			RelationshipChainPosition pos = rStore.getRelationshipChainPosition(node);
			Iterator<RelationshipData> rels = rStore.getMoreRelationships(node, pos).GetEnumerator();
			assertTrue(!rels.MoveNext());
			nStore.deleteNode(node);
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void deleteNode2(int node, int prop1, int prop2, int prop3) throws IOException
		private void deleteNode2(int node, int prop1, int prop2, int prop3)
		{
			ArrayMap<int, PropertyData> props = nStore.getProperties(node);
			int count = 0;
			foreach (int keyId in props.Keys)
			{
				int id = props.get(keyId).getId();
				PropertyRecord record = pStore.getRecord(id);
				PropertyData data = new PropertyData(id, getValue(record));
				if (data.getId() == prop1)
				{
					assertEquals("prop1", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals("-string2", data.Value);
				}
				else if (data.getId() == prop2)
				{
					assertEquals("prop2", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new int(-2), data.Value);
				}
				else if (data.getId() == prop3)
				{
					assertEquals("prop3", MyPropertyIndex.getIndexFor(keyId).Key);
					assertEquals(new bool(true), data.Value);
					nStore.removeProperty(node, prop3);
				}
				else
				{
					throw new IOException();
				}
				count++;
			}
			assertEquals(3, count);
			assertEquals(2, nStore.getProperties(node).size());
			RelationshipChainPosition pos = rStore.getRelationshipChainPosition(node);
			Iterator<RelationshipData> rels = rStore.getMoreRelationships(node, pos).GetEnumerator();
			assertTrue(!rels.MoveNext());
			nStore.deleteNode(node);
		}

		private void testGetRels(int[] relIds)
		{
			for (int i = 0; i < relIds.Length; i++)
			{
				assertEquals(null, rStore.getRelationship(relIds[i]));
			}
		}

		public virtual void testRels1()
		{
			try
			{
				initializeStores();
				startTx();
				int relType1 = ds.nextId(typeof(RelationshipType));
				relTypeStore.addRelationshipType(relType1, "relationshiptype1");
				int[] nodeIds = new int[3];
				for (int i = 0; i < 3; i++)
				{
					nodeIds[i] = ds.nextId(typeof(Node));
					nStore.createNode(nodeIds[i]);
					nStore.addProperty(nodeIds[i], pStore.nextId(), index("nisse"), new int(10 - i));
				}
				for (int i = 0; i < 2; i++)
				{
					rStore.createRelationship(ds.nextId(typeof(Relationship)), nodeIds[i], nodeIds[i + 1], relType1);
				}
				commitTx();
				startTx();
				for (int i = 0; i < 3; i++)
				{
					RelationshipChainPosition pos = rStore.getRelationshipChainPosition(nodeIds[i]);
					foreach (RelationshipData rel in rStore.getMoreRelationships(nodeIds[i], pos))
					{
						rStore.deleteRelationship(rel.getId());
					}
					nStore.deleteNode(nodeIds[i]);
				}
				commitTx();
				ds.Close();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				fail("" + e);
			}
		}

		public virtual void testRels2()
		{
			try
			{
				initializeStores();
				startTx();
				int relType1 = ds.nextId(typeof(RelationshipType));
				relTypeStore.addRelationshipType(relType1, "relationshiptype1");
				int[] nodeIds = new int[3];
				for (int i = 0; i < 3; i++)
				{
					nodeIds[i] = ds.nextId(typeof(Node));
					nStore.createNode(nodeIds[i]);
					nStore.addProperty(nodeIds[i], pStore.nextId(), index("nisse"), new int(10 - i));
				}
				for (int i = 0; i < 2; i++)
				{
					rStore.createRelationship(ds.nextId(typeof(Relationship)), nodeIds[i], nodeIds[i + 1], relType1);
				}
				rStore.createRelationship(ds.nextId(typeof(Relationship)), nodeIds[0], nodeIds[2], relType1);
				commitTx();
				startTx();
				for (int i = 0; i < 3; i++)
				{
					RelationshipChainPosition pos = rStore.getRelationshipChainPosition(nodeIds[i]);
					foreach (RelationshipData rel in rStore.getMoreRelationships(nodeIds[i], pos))
					{
						rStore.deleteRelationship(rel.getId());
					}
					nStore.deleteNode(nodeIds[i]);
				}
				commitTx();
				ds.Close();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				fail("" + e);
			}
		}

		public virtual void testRels3()
		{
		// test linked list stuff during relationship delete
			try
			{
				initializeStores();
				startTx();
				int relType1 = ds.nextId(typeof(RelationshipType));
				relTypeStore.addRelationshipType(relType1, "relationshiptype1");
				int[] nodeIds = new int[8];
				for (int i = 0; i < nodeIds.Length; i++)
				{
					nodeIds[i] = ds.nextId(typeof(Node));
					nStore.createNode(nodeIds[i]);
				}
				for (int i = 0; i < nodeIds.Length / 2; i++)
				{
					rStore.createRelationship(ds.nextId(typeof(Relationship)), nodeIds[i], nodeIds[i * 2], relType1);
				}
				int rel5 = ds.nextId(typeof(Relationship));
				rStore.createRelationship(rel5, nodeIds[0], nodeIds[5], relType1);
				int rel2 = ds.nextId(typeof(Relationship));
				rStore.createRelationship(rel2, nodeIds[1], nodeIds[2], relType1);
				int rel3 = ds.nextId(typeof(Relationship));
				rStore.createRelationship(rel3, nodeIds[1], nodeIds[3], relType1);
				int rel6 = ds.nextId(typeof(Relationship));
				rStore.createRelationship(rel6, nodeIds[1], nodeIds[6], relType1);
				int rel1 = ds.nextId(typeof(Relationship));
				rStore.createRelationship(rel1, nodeIds[0], nodeIds[1], relType1);
				int rel4 = ds.nextId(typeof(Relationship));
				rStore.createRelationship(rel4, nodeIds[0], nodeIds[4], relType1);
				int rel7 = ds.nextId(typeof(Relationship));
				rStore.createRelationship(rel7, nodeIds[0], nodeIds[7], relType1);
				commitTx();
				startTx();
				rStore.deleteRelationship(rel7);
				rStore.deleteRelationship(rel4);
				rStore.deleteRelationship(rel1);
				rStore.deleteRelationship(rel6);
				rStore.deleteRelationship(rel3);
				rStore.deleteRelationship(rel2);
				rStore.deleteRelationship(rel5);
			// nStore.deleteNode( nodeIds[2] );
			// nStore.deleteNode( nodeIds[3] );
			// nStore.deleteNode( nodeIds[1] );
			// nStore.deleteNode( nodeIds[4] );
			// nStore.deleteNode( nodeIds[0] );
				commitTx();
				ds.Close();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				fail("" + e);
			}
		}

		public virtual void testProps1()
		{
			try
			{
				initializeStores();
				startTx();
				int nodeId = ds.nextId(typeof(Node));
				nStore.createNode(nodeId);
				int propertyId = pStore.nextId();
				nStore.addProperty(nodeId, propertyId, index("nisse"), new int(10));
				commitTx();
				ds.Close();
				initializeStores();
				startTx();
				nStore.changeProperty(nodeId, propertyId, new int(5));
				nStore.removeProperty(nodeId, propertyId);
				nStore.deleteNode(nodeId);
				commitTx();
				ds.Close();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				fail("" + e);
			}
		}
	}
}